package cn.usbtg.jfinal.plugin.autoroute.handler;

import cn.usbtg.jfinal.plugin.autoroute.AutoRoutesAnnotation;
import cn.usbtg.jfinal.plugin.autoroute.HttpRequestMethod;
import cn.usbtg.jfinal.plugin.autoroute.ManualRoute;
import com.jfinal.handler.Handler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 基于正则的url转发到jfinal路由
 * 根据配置决定是否加入到缓存
 */
public class ManualRouteHandler extends Handler {
    private final Logger log = LoggerFactory.getLogger(ManualRouteHandler.class);

    @Override
    public void handle(String target, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, boolean[] handlers) {
        long t = System.currentTimeMillis();
        AutoRoutesAnnotation autoRoutesAnnotation = AutoRoutesAnnotation.getInstance();

        String httpMethod = httpServletRequest.getMethod();
        String url = httpMethod + ":" + target;

        //已经解析过的直接转发
        ManualRoute manualRoute = autoRoutesAnnotation.getManualRouteMap().get(url);
        if (manualRoute != null) {
            for (Map.Entry<String, String> entry : manualRoute.getParams().entrySet()) {
                httpServletRequest.setAttribute(entry.getKey(), entry.getValue());
            }

            log.debug("CACHE:" + manualRoute.getInfo() + "," + (System.currentTimeMillis() - t) + "ms");

            next.handle(manualRoute.getNativeUrl(), httpServletRequest, httpServletResponse, handlers);
            return;
        }

        //未解析过的，解析后转发，并视是否启用缓存添加到已解析记录
        Map<String, ManualRoute> manualRouteRegMap = autoRoutesAnnotation.getManualRouteRegMap();
        for (Map.Entry<String, ManualRoute> entry : manualRouteRegMap.entrySet()) {
            ManualRoute manualRouteReg = entry.getValue();

            Matcher m = manualRouteReg.getPattern().matcher(url);
            if (!m.find()) {
                continue;
            }

            ManualRoute manualRouteCopy = new ManualRoute();
            manualRouteCopy.setUrl(url);
            manualRouteCopy.setMethod(HttpRequestMethod.parse(httpMethod));
            manualRouteCopy.setNativeUrl(manualRouteReg.getNativeUrl());

            List<String> keyList = new ArrayList<>();
            String urlZw = manualRouteReg.getUrl();
            String urlZwReg = "^" + urlZw.replaceAll(autoRoutesAnnotation.getParamKeyRegStr(), autoRoutesAnnotation.getParamKeyReplaceRegStr()) + "$";
            Pattern kp = Pattern.compile(urlZwReg);
            Matcher km = kp.matcher(urlZw);
            if (km.find()) {
                for (int i = 1; i <= km.groupCount(); i++) {
                    keyList.add(km.group(i));
                }
            }

            Pattern vp = manualRouteReg.getPattern();
            Matcher vm = vp.matcher(url);
            if (vm.find()) {
                for (int i = 1; i <= vm.groupCount(); i++) {
                    String paramName = "path." + keyList.get(i - 1);
                    String paramValue = vm.group(i);
                    manualRouteCopy.getParams().put(paramName, paramValue);
                    httpServletRequest.setAttribute(paramName, paramValue);
                }
            }

            if (manualRouteReg.isCache()) {
                autoRoutesAnnotation.getManualRouteMap().put(url, manualRouteCopy);
            }

            log.debug(manualRouteCopy.getInfo() + "," + (System.currentTimeMillis() - t) + "ms");

            next.handle(manualRouteReg.getNativeUrl(), httpServletRequest, httpServletResponse, handlers);
            return;
        }

        next.handle(target, httpServletRequest, httpServletResponse, handlers);
    }
}